﻿


Namespace YahooManaged.Finance.Indicators

    ''' <summary>
    ''' Standard Deviation Indicator
    ''' </summary>
    ''' <remarks></remarks>
    Public Class StD
        Implements ISingleValueIndicator

        Public Overridable ReadOnly Property Name() As String Implements IIndicator.Name
            Get
                Return "Standard Deviation"
            End Get
        End Property

        Public Overridable ReadOnly Property IsRealative As Boolean Implements IIndicator.IsRealative
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property ScaleMaximum() As Double Implements IIndicator.ScaleMaximum
            Get
                Return Double.PositiveInfinity
            End Get
        End Property

        Public ReadOnly Property ScaleMinimum() As Double Implements IIndicator.ScaleMinimum
            Get
                Return 0
            End Get
        End Property

        Public Property Period() As Integer Implements IIndicator.Period
            Get
                Return mMA.Period
            End Get
            Set(ByVal value As Integer)
                mMA.Period = value
            End Set
        End Property
        Public Property PopulationStandardDeviation As Boolean = True


        Private mMA As New MA

        ''' <summary>
        ''' Calculates values of Standard Deviation for historic quote values.
        ''' </summary>
        ''' <param name="values">An unsorted IEnumerable of HistQuoteData.</param>
        ''' <returns>The sorted dictionaries. 1) StD values; 2) MA values; 3) Quote values.</returns>
        ''' <remarks></remarks>
        Public Overridable Function Calculate(ByVal values As IEnumerable(Of KeyValuePair(Of Date, Double))) As Dictionary(Of Date, Double)() Implements ISingleValueIndicator.Calculate
            Dim stdResult As New Dictionary(Of Date, Double)

            Dim baseResults = mMA.Calculate(values)
            Dim maResult As Dictionary(Of Date, Double) = baseResults(0)
            Dim histQuotes As New List(Of KeyValuePair(Of Date, Double))(baseResults(1))

            If histQuotes.Count > 0 Then
                Dim tempResult As Double = 0
                stdResult.Add(histQuotes(0).Key, 0)
                For i As Integer = 1 To histQuotes.Count - 1
                    tempResult = 0
                    If i >= mMA.Period - 1 Then
                        For n As Integer = i - mMA.Period + 1 To i
                            tempResult += (histQuotes(n).Value - maResult(histQuotes(i).Key)) ^ 2
                        Next
                        tempResult /= (mMA.Period + CInt(IIf(Me.PopulationStandardDeviation, 0, -1)))
                    Else
                        For n As Integer = 0 To i
                            tempResult += (histQuotes(n).Value - maResult(histQuotes(i).Key)) ^ 2
                        Next
                        tempResult /= (i + CInt(IIf(Me.PopulationStandardDeviation, 1, 0)))
                    End If
                    tempResult = Math.Sqrt(tempResult)
                    stdResult.Add(histQuotes(i).Key, tempResult)
                Next
            End If

            Return New Dictionary(Of Date, Double)() {stdResult, maResult, baseResults(1)}
        End Function


        Public Overrides Function ToString() As String
            Return Me.Name & " " & Me.Period
        End Function

    End Class


End Namespace